package com.itheima.tanhua.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.tanhua.api.*;
import com.itheima.tanhua.autoconfig.template.HuanXinTemplate;
import com.itheima.tanhua.domain.Question;
import com.itheima.tanhua.dto.RecommendUserDto;
import com.itheima.tanhua.exception.BusinessException;
import com.itheima.tanhua.mongo.RecommendUser;
import com.itheima.tanhua.domain.UserInfo;
import com.itheima.tanhua.mongo.UserLike;
import com.itheima.tanhua.mongo.Visitors;
import com.itheima.tanhua.utils.Constants;
import com.itheima.tanhua.utils.UserHolder;
import com.itheima.tanhua.vo.ErrorResult;
import com.itheima.tanhua.vo.NearUserVo;
import com.itheima.tanhua.vo.PageResult;
import com.itheima.tanhua.vo.TodayBest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Lff
 * @date 2022/3/25
 */
@Service
public class TanHuaService {
    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private TanHuaApi tanHuaApi;

    @DubboReference
    private QuestionApi questionApi;

    @DubboReference
    private RecommendApi recommendApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @DubboReference
    private FriendApi friendApi;

    @Autowired
    private HuanXinTemplate hx;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    /*@Value("${tanhua.default.recommend.users}")
    private String recommendIds;*/

    @DubboReference
    private UserLocationApi userLocationApi;

    public TodayBest getTodayBest() {
        //获取当前登录用户的id
        Long id = UserHolder.getUser().getId();
        //调用api查询今日最佳用户的id
        RecommendUser recommendUser = tanHuaApi.queryByToUserIdWithScoreMax(id);
        if (recommendUser == null) {
            //设置默认值
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1l);
            recommendUser.setScore(100d);
        }
        //查询佳人信息
        UserInfo todayBestInfo = userInfoApi.findById(recommendUser.getUserId());
        //转换成vo对象并返回
        TodayBest result = TodayBest.init(todayBestInfo, recommendUser);
        return result;

    }

    /**
     * 分页获取推荐好友列表
     * 先查mongo获取ids，根据ids去mysql获取用户详情信息
     *
     * @param dto
     * @return
     */
    public PageResult getRecommendUsers(RecommendUserDto dto) {
        //获取当前用户id
        Long id = UserHolder.getUser().getId();
        //调用monggo获取推荐的好友的id7
        PageResult result = recommendApi.queryToUserWithPages(id, dto.getPage(), dto.getPagesize());
        List<RecommendUser> items = (List<RecommendUser>) result.getItems();
        //设置当前页码
        result.setPage(dto.getPage());
        //设置当前页码长度
        result.setPagesize(dto.getPagesize());
        if (items == null || items.size() == 0) {
            //封装
            result.setCounts(0l);
            result.setPages(0l);
            return result;
        }
        //根据ids查询
        Page<UserInfo> pages = userInfoApi.getUserToPage(items, dto);
        //填充总记录数
        result.setCounts(pages.getTotal());
        //填充当前分页总页数
        result.setPages(pages.getPages());
        List<RecommendUser> lists = (List<RecommendUser>) result.getItems();
        //处理数据
        Map<Long, Double> maps = lists.stream().collect(Collectors.toMap(RecommendUser::getUserId,
                RecommendUser::getScore));
        //转化为ToDayBest
        List<TodayBest> todayBests = TodayBest.initList(pages.getRecords(), maps);
        //填充数据
        result.setItems(todayBests);
        return result;
    }

    /**
     * 根据id获取佳人详情信息
     *
     * @param bestUserId 佳人id
     * @return
     */
    public TodayBest getPersonalInfo(Long bestUserId) {
        //根据当前用户id和佳人id调用mogonApi查询recommend
        //获取当前登陆用用户的id
        Long toUserId = UserHolder.getUser().getId();
        RecommendUser recommendUser = recommendApi.findRecommendUserOne(toUserId, bestUserId);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(bestUserId);
            recommendUser.setScore(99.99);
            recommendUser.setToUserId(toUserId);
        }

        //调用visitorsApi保存访问记录
        if (UserHolder.getUser().getId() != bestUserId) {
            Visitors visitors = new Visitors();
            visitors.setDate(System.currentTimeMillis());
            visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
            visitors.setFrom("首页");
            visitors.setScore(recommendUser.getScore());
            visitors.setUserId(bestUserId);
            visitors.setVisitorUserId(toUserId);
            //保存来访信息
            visitorsApi.save(visitors);
        }

        //调用mysqlapi查询UserInfo
        UserInfo userInfo = userInfoApi.findById(bestUserId);
        //初始化返回值
        TodayBest result = TodayBest.init(userInfo, recommendUser);
        //返回
        return result;
    }

    /**
     * 获取陌生人问题
     *
     * @param userId
     * @return
     */
    public String getStrangerQuestionsById(Long userId) {
        Question question = questionApi.findByUserId(userId);
        if (question == null) {
            return "你喜欢Java吗？";
        }
        return question.getTxt();
    }

    /**
     * 回复问题
     *
     * @param toUserId 消息接收者的id
     * @param reply
     * @return
     */
    public void replyStrangerQuestions(Long toUserId, String reply) {
        //获取当前操作人id
        Long id = UserHolder.getUser().getId();
        //构建消息发送者环信id
        String hxUser = Constants.HX_USER_PREFIX + id;
        //构建消息接收者环信id
        String toHxUser = Constants.HX_USER_PREFIX + toUserId;
        //查询消息发送者的信息
        UserInfo info = userInfoApi.findById(id);
        //构建消息对象
        Map messages = new HashMap<>();
        messages.put("userId", id);
        messages.put("huanXinId", hxUser);
        messages.put("nickname", info.getNickname());
        messages.put("strangerQuestion", getStrangerQuestionsById(toUserId));
        messages.put("reply", reply);
        //转成Json
        String message = JSON.toJSONString(messages);
        //发送消息
        Boolean aBoolean = huanXinTemplate.sendMsg(toHxUser, message);
        System.out.println(aBoolean);
    }

    /**
     * 获取推荐用户集合
     * 排除掉已经喜欢/不喜欢的用户列表
     *
     * @return
     */
    public List<TodayBest> findCardsToTodayBest() {
        //查询推荐用户
        //获取当前用户id
        Long id = UserHolder.getUser().getId();
        List<RecommendUser> recommendUsers = recommendApi.queryRandomList(id, 10);
        //如果为空构建默认数据
        boolean isDefault = false;
        if (CollUtil.isEmpty(recommendUsers)) {
            //从缓存里获取数据
            String s = (String) redisTemplate.opsForValue().get(Constants.DEFAULT_CARDS_LIST);
            List<TodayBest> list = JSON.parseObject(s, List.class);
            if (list != null) {
                return list;
            }
            //String[] ids = recommendIds.split(",");
            String[] ids = new String[]{"1", "32", "27", "6", "4", "8", "16", "23", "25", "15"};
            Arrays.stream(ids).forEach(rid -> {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setToUserId(id);
                recommendUser.setUserId(Convert.toLong(rid));
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUsers.add(recommendUser);
            });
            //是默认数据
            isDefault = true;
        }
        //抽取id查询mysql
        List<Long> userIds = recommendUsers.stream().map(r -> r.getUserId()).collect(Collectors.toList());
        Map<Long, UserInfo> userMap = userInfoApi.getUserInfosToMap(userIds, null);

        //封装数据
        List<TodayBest> results = recommendUsers.stream().map(re -> {
            TodayBest init = TodayBest.init(userMap.get(re.getUserId()), re);
            return init;
        }).collect(Collectors.toList());
        if (isDefault) {
            redisTemplate.opsForValue().set(Constants.DEFAULT_CARDS_LIST, JSON.toJSONString(results));
        }
        //返回
        return results;
    }

    /**
     * 喜欢
     *
     * @param likeUserId
     */
    public void toLove(Long likeUserId) {
        Long userId = UserHolder.getUser().getId();
        //操作mongo添加喜欢数据
        UserLike userLike = new UserLike();
        userLike.setIsLike(true);
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        Boolean flag = userLikeApi.saveOrUpdate(userLike);
        if (!flag) {
            throw new BusinessException(ErrorResult.error());
        }
        //更改缓存中的信息
        //喜欢
        redisTemplate.opsForSet().add(Constants.USER_LIKE_SET + userId, likeUserId.toString());
        //不喜欢
        redisTemplate.opsForSet().remove(Constants.USER_DISLIKE_SET + userId, likeUserId.toString());
        //判断是否互相喜欢
        if (isLike(UserHolder.getUser().getId(), likeUserId)) {
            //添加好友关系
            friendApi.saveFriendRelation(userId, likeUserId);
            //添加环信的好友关系
            hx.addContact("hx" + userId, "hx" + likeUserId);
            //更改状态 互相喜欢的状态
            userLikeApi.updateAlreadyLove(userId, likeUserId, true);
        }
    }


    /**
     * 不喜欢
     *
     * @param likeUserId
     */
    public void toUnLove(Long likeUserId) {
        Long userId = UserHolder.getUser().getId();
        //操作mongo添加喜欢数据
        UserLike userLike = new UserLike();
        userLike.setIsLike(false);
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        //添加或修改成不喜欢
        Boolean flag = userLikeApi.saveOrUpdate(userLike);
        if (!flag) {
            throw new BusinessException(ErrorResult.error());
        }
        //更改缓存中的信息
        //喜欢
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_SET + userId, likeUserId.toString());
        //不喜欢
        redisTemplate.opsForSet().add(Constants.USER_DISLIKE_SET + userId, likeUserId.toString());
        //更改数据库

        //判断是否互相喜欢
        if (userLikeApi.isAlreadyLove(userId,likeUserId)) {
            //删除好友关系
            friendApi.deleteFriendRelation(userId, likeUserId);
            //删除环信的好友关系
            hx.deleteContact("hx" + userId, "hx" + likeUserId);
            //更改互相喜欢状态
            userLikeApi.updateAlreadyLove(userId, likeUserId, false);
        }
    }

    /**
     * 判断用户是否相喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    private boolean isLike(Long userId, Long likeUserId) {
        if (redisTemplate.opsForSet().isMember(Constants.USER_LIKE_SET + userId, likeUserId.toString())) {
            return true;
        } else {
            //数据库判断是否是
            boolean flag = userLikeApi.hasLikeRelation(userId, likeUserId);
            if (flag) {
                //重新加入缓存
                redisTemplate.opsForSet().add(Constants.USER_LIKE_SET + userId, likeUserId.toString());
                redisTemplate.opsForSet().remove(Constants.USER_DISLIKE_SET + userId, likeUserId.toString());
            }
            return flag;
        }
    }

    /**
     * 搜索附近的人
     *
     * @param gender
     * @param distance
     * @return
     */
    public List<NearUserVo> searchNear(String gender, Double distance) {
        //获取当前user的Id
        Long userId = UserHolder.getUser().getId();
        //调用Api查询
        List<Long> userIds = userLocationApi.searchNear(distance, userId);
        if (CollUtil.isEmpty(userIds)) {
            return null;
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> userMap = userInfoApi.getUserInfosToMap(userIds, userInfo);
        //填充对象
        ArrayList<NearUserVo> result = new ArrayList<>();
        for (Long id : userIds) {
            //排除当前用户
            if (userId == id) {
                continue;
            }
            UserInfo info = userMap.get(id);
            if (info != null) {
                NearUserVo vo = NearUserVo.init(info);
                result.add(vo);
            }
        }
        //返回结果
        return result;
    }
}
